package io.awen.modules.sign.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import io.awen.common.exception.RRException;
import io.awen.common.utils.GeoUtils;
import io.awen.common.utils.PageUtils;
import io.awen.common.utils.DistanceUtil;
import io.awen.common.utils.Query;
import io.awen.config.MqttConfig;
import io.awen.modules.sign.StatusConstants;
import io.awen.modules.sign.dao.SignTaskOperationDao;
import io.awen.modules.sign.entity.*;
import io.awen.modules.sign.service.*;
import io.awen.modules.sys.qo.SysUserQo;
import io.awen.modules.sys.service.SysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;


@Service("signTaskOperationService")
public class SignTaskOperationServiceImpl extends ServiceImpl<SignTaskOperationDao, SignTaskOperationEntity> implements SignTaskOperationService {

    @Autowired
    private SignTaskService signTaskService;

    @Autowired
    private SignCarWeightChangeService signCarWeightChangeService;
    @Autowired
    private SignCarDispatchService signCarDispatchService;
    @Autowired
    private SignContainerAlarmService signContainerAlarmService;
    @Autowired
    private SignCarLonLatService signCarLonLatService;
    @Autowired
    private MqttConfig mqttConfig;
    @Autowired
    private SysUserService sysUserService;

    private final static Gson gson = new Gson();

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SignTaskOperationEntity> page = this.page(
                new Query<SignTaskOperationEntity>().getPage(params),
                new QueryWrapper<SignTaskOperationEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void agree(SignTaskOperationEntity signTaskOperation) {
        if (signTaskOperation.getTaskId() == null) {
            throw new RRException("请选择收运任务");
        }

        SignTaskEntity task = signTaskService.getById(signTaskOperation.getTaskId());
        if (task == null) {
            throw new RRException("没有该收运任务");
        }
        if (!StatusConstants.TASK_STATUS_WAITED.equals(task.getStatus())) {
            throw new RRException("该收运任务不处于等待状态");
        }

        signTaskOperation.setStatus(StatusConstants.OPER_STATUS_AGREE);
        save(signTaskOperation);

        task.setStatus(StatusConstants.TASK_STATUS_PROCESSING);
        task.setExecuteDay(new Date());
        signTaskService.updateById(task);

        SignCarDispatchEntity dispatch = signCarDispatchService.getById(task.getDispatchId());
        dispatch.setStatus(StatusConstants.TASK_STATUS_PROCESSING);
        signCarDispatchService.updateById(dispatch);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void reject(SignTaskOperationEntity signTaskOperation) {
        if (signTaskOperation.getTaskId() == null) {
            throw new RRException("请选择收运任务");
        }

        SignTaskEntity task = signTaskService.getById(signTaskOperation.getTaskId());
        if (task == null) {
            throw new RRException("没有该收运任务");
        }
        if (!StatusConstants.TASK_STATUS_WAITED.equals(task.getStatus())) {
            throw new RRException("该收运任务不处于等待状态");
        }

        signTaskOperation.setStatus(StatusConstants.OPER_STATUS_REJECT);
        save(signTaskOperation);

        task.setStatus(StatusConstants.TASK_STATUS_REJECT);
        signTaskService.updateById(task);

        SignCarDispatchEntity dispatch = signCarDispatchService.getById(task.getDispatchId());
        dispatch.setStatus(StatusConstants.TASK_STATUS_REJECT);
        signCarDispatchService.updateById(dispatch);

        if (dispatch.getResidueCalCount() == 0) {
            // 通知收运单位管理员
            SysUserQo qo = new SysUserQo();
//            qo.setCtUnitId(dispatch.getCtUnitId());
            qo.setRoleName("收运单位管理员");
            List<SysUserQo> userList = sysUserService.queryByRoleName(qo);
            if (userList.size() > 0) {
                mqttConfig.getMqttPushClient().publish(1, false, "dispatch_" + userList.get(0).getUserId(), gson.toJson(dispatch));
            }

        } else {
            signTaskService.autoTask(dispatch);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submit(SignTaskOperationEntity signTaskOperation) {
        if (signTaskOperation.getTaskId() == null) {
            throw new RRException("请选择收运任务");
        }

        SignTaskEntity task = signTaskService.getById(signTaskOperation.getTaskId());
        if (task == null) {
            throw new RRException("没有该收运任务");
        }

        if (!StatusConstants.TASK_STATUS_PROCESSING.equals(task.getStatus()) && !StatusConstants.TASK_STATUS_FINISH.equals(task.getStatus())) {
            throw new RRException("该收运任务不能提交：" + task.getStatus());
        }

//        if (!StatusConstants.TASK_STATUS_PROCESSING.equals(task.getStatus())) {
//            throw new RRException("该收运任务不能提交：" + StatusConstants.TASK_STATUS_PROCESSING);
//        }

        SignCarWeightChangeEntity weightChange = signCarWeightChangeService.getOne(new QueryWrapper<SignCarWeightChangeEntity>()
                .eq("sign_car_id", task.getDispatchCarId())
                .eq("state", 0)//停止状态的过滤出来
                .eq("bind", 0)//未绑定的过滤出来
                .orderByDesc("id")
                .last("limit 1"));
        if (weightChange == null) {
            throw new RRException("没有对应的重量信息,可能车辆已启动,或者二次提交");
        }

        //任务调度表的提交
        if (signTaskOperation.getContainerId() != null) {
            signTaskOperation.setContainerId(signTaskOperation.getContainerId());
        } else if (signTaskOperation.getSinkId() != null) {
            signTaskOperation.setSinkId(signTaskOperation.getSinkId());
            signTaskOperation.setSyWeight(weightChange.getEndWeight());
            //查询同任务id的最早一条记录，并将sy_weight设置为该记录的end_weight
            SignTaskOperationEntity operation = getOne(new QueryWrapper<SignTaskOperationEntity>()
                    .eq("task_id", signTaskOperation.getTaskId())
                    .orderByAsc("id")
                    .last("limit 1"));
            if (operation != null) {
                operation.setSyWeight(weightChange.getEndWeight());
                save(operation);
            }
        } else {
            throw new RRException("未知的收运动作");
        }
        signTaskOperation.setStatus(StatusConstants.OPER_STATUS_SUBMIT);
        signTaskOperation.setChangeId(weightChange.getId());
        save(signTaskOperation);
        //任务表的状态更改,如果是处理中，提交后变为处理完成，如果是处理完成，提交后变为全部完成
        if (task.getStatus().equals(StatusConstants.TASK_STATUS_PROCESSING)) {
            task.setStatus(StatusConstants.TASK_STATUS_FINISH);
        } else if (task.getStatus().equals(StatusConstants.TASK_STATUS_FINISH)) {
            task.setStatus(StatusConstants.TASK_STATUS_FINISH_ALL);
            //获取sign_car_lon_lat表从开始拉运到卸水的所有记录，通过经纬度的差值计算出里程数，更新到task表中
            SignCarWeightChangeEntity start = signCarWeightChangeService.getOne(new QueryWrapper<SignCarWeightChangeEntity>()
                    .eq("sign_car_id", task.getDispatchCarId())
                    .eq("state", 1)//装货的过滤出来
                    .eq("bind", 1)//绑定的过滤出来
                    .orderByDesc("id")
                    .last("limit 1"));
            List<SignCarLonLatEntity> list = signCarLonLatService.list(new QueryWrapper<SignCarLonLatEntity>()
                    .eq("car_id", task.getDispatchCarId())
                    .ge("create_time", start.getCreateTime())
                    .le("create_time", weightChange.getCreateTime())
                    .orderByAsc("id"));
            double distance = 0;
            for (int i = 0; i < list.size() - 1; i++) {
                distance += DistanceUtil.getDistance(list.get(i).getLon(), list.get(i).getLat(), list.get(i + 1).getLon(), list.get(i + 1).getLat());
            }
            task.setDistance(distance);
        }
        task.setEndTime(new Date());
        signTaskService.updateById(task);
        //车辆调度表的状态更改
        SignCarDispatchEntity dispatch = signCarDispatchService.getById(task.getDispatchId());
        dispatch.setStatus(StatusConstants.TASK_STATUS_FINISH);
        dispatch.setSyWeight(Double.valueOf(signTaskOperation.getSyWeight()));
        signCarDispatchService.updateById(dispatch);
        //报警表的状态更改
        if (dispatch.getAlarmId() != null) {
            SignContainerAlarmEntity alarm = signContainerAlarmService.getById(dispatch.getAlarmId());
            alarm.setStatus(StatusConstants.ALARM_STATUS_FINISH);
            signContainerAlarmService.updateById(alarm);
        }
        //载重变化表的状态更改
        weightChange.setBind(1);
    }

}